from epics import PV
from pcaspy import SimpleServer, Driver
import threading
import time
from os import environ
#mod_list = ["SlitH1","SlitH2","SlitV1","SlitV2"]
mod_list = ["SlitH2","SlitV2"]
DATA_COUNT = 2000                   # 采集数据的大小，默认为2000个点，根据需求修改（测剖面所需时间×采集频率）
Power_DATA_PV = "iLINAC:mod1_FC1_Rd_Avg"             # 采集的数据PV名设定
OUT_DATA_Y_PV = "iLINAC:{}_Data_Y"              # 采集数据后，输出的PV名设定
OUT_DATA_X_PV = "iLINAC:{}_Data_X"              # 采集数据后，输出的PV名设定
OPR_PV = "iLINAC:{}_Opr"                      # 采集开关PV名设定
Pos_read = "iLINAC:dActPos_{}"
Start_Pos = "iLINAC:dStartPos_{}"
End_Pos = "iLINAC:dEndPos_{}"
Pos_Opr = "iLINAC:bCmdSectionMove_{}"
Acquisition_frequency = 10                      # 数据采集频率：一秒钟采集多少数据，最多为100
EPICS_CA_ADDR_LIST = "127.0.0.1 192.168.1.26 192.168.1.27"    # 采集数据PV所在服务器的IP地址，默认为localhost
EPICS_CAS_SERVER_PORT = "5064"      # 本IOC服务器的端口号，默认为5064

class Profile_measurement(threading.Thread):
    def __init__(self,setParam,index) -> None:
        self.index = index
        print(mod_list[self.index]+" is run")
        self.Flag = 0
        threading.Thread.__init__(self)
        self.setParam = setParam
        self.inpv = PV(OPR_PV.format(mod_list[self.index]), callback=self.onValueChange)
        self.data = PV(Power_DATA_PV)
        self.Pos_read = PV(Pos_read.format(mod_list[self.index]))
        self.Start_Pos = PV(Start_Pos.format(mod_list[self.index]))
        self.End_Pos = PV(End_Pos.format(mod_list[self.index]))
        self.Pos_Opr = PV(Pos_Opr.format(mod_list[self.index]))
        self.runFlag = 0
        self.result_y = []
        self.result_x = []
        try:
            self.start()
        except:
            print("Error: No data")
    def onValueChange(self,pvname=None, value=None, host=None, **kws):
        if value == 1:
            self.Flag = 1
        elif value == 0:
            self.Flag = 0
        elif value == 2:
            self.Flag = 0
            self.runFlag = 0
            self.result_y = []
            self.result_x = []
            self.setParam(OUT_DATA_Y_PV.format(mod_list[self.index]),[0 for i in range(DATA_COUNT)])
            self.setParam(OUT_DATA_X_PV.format(mod_list[self.index]),[0 for i in range(DATA_COUNT)])
    def pos_calc(self):
        pos_data = self.Pos_read.get()
        now_pos = pos_data - self.End_Pos.get()
        if now_pos > self.old_min_pos:
            self.old_min_pos = now_pos
        if pos_data >= self.Start_Pos.get() and pos_data <= self.End_Pos.get() and now_pos >= self.old_min_pos:
            return True,pos_data
        else:
            return False,pos_data

    def run(self):
        while True:
            if self.Flag == 0: # 采集结束的标识
                time.sleep(0.01)
            if self.Flag == 1:
                if self.runFlag == 0:
                    self.old_min_pos = self.Pos_read.get() - self.End_Pos.get()
                    self.runFlag = 1
                    self.Pos_Opr.put(1)
                pos_flag,pos_data = self.pos_calc()
                if pos_flag:
                    print(mod_list[self.index]+" 开始采集")
                    while pos_flag:
                        pos_flag,pos_data = self.pos_calc()
                        if len(self.result_y) == DATA_COUNT:
                            self.result_y.pop(0)
                        if len(self.result_x) == DATA_COUNT:
                            self.result_x.pop(0)
                        self.result_y.append(self.data.get())
                        self.result_x.append(pos_data)
                        self.setParam(OUT_DATA_Y_PV.format(mod_list[self.index]),self.result_y)
                        self.setParam(OUT_DATA_X_PV.format(mod_list[self.index]),self.result_x)
                        time.sleep(1/Acquisition_frequency)
                    print("采集数据长度Y:\t",len(self.result_y))
                    print("采集数据长度X:\t",len(self.result_x))
                    print(mod_list[self.index]+" 停止采集")
                    self.inpv.put(0)
                    self.Pos_Opr.put(0)
                else:
                    time.sleep(0.01)

class myDriver(Driver):
    def __init__(self):
        super(myDriver, self).__init__()
        for i in range(len(mod_list)):
            Profile_measurement(self.setParam,i)



if __name__ == '__main__':
    environ["EPICS_CA_ADDR_LIST"] = EPICS_CA_ADDR_LIST
    environ["EPICS_CA_AUTO_ADDR_LIST"] = "no"
    environ["EPICS_CAS_SERVER_PORT"] = EPICS_CAS_SERVER_PORT
    prefix = ''
    pvdb = {}
    for mod in mod_list:
        pvdb[OPR_PV.format(mod)] = {
                'type': 'enum',
                'enums': ('STOP', 'RUN','Reset'),
            }
        pvdb[OUT_DATA_Y_PV.format(mod)] = {
                'scan': 1,
                'prec': '3',
                'count' : DATA_COUNT,
            }
        pvdb[OUT_DATA_X_PV.format(mod)] = {
                'scan': 1,
                'prec': '3',
                'count' : DATA_COUNT,
            }
    server = SimpleServer()
    server.createPV(prefix, pvdb)
    driver = myDriver()
    while True:
    # process CA transactions
        server.process(0.1)
